package cn.com.vs.service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpStatus;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;

import cn.com.vs.service.mapper.WeatherMapper;
import cn.com.vs.utils.DBUtils;
//import cn.com.vs.utils.SmartWeatherUrlUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

public final class WeatherService {
	private static Logger logger = Logger.getLogger(WeatherService.class);
	HttpRequestFactory requestFactory = null;
	JsonFactory JSON_FACTORY = null;
	private static WeatherService instance = new WeatherService();
	public static WeatherService getInstance(){
		return instance;
	}
	Cache<String,JSONObject> weatherCache = CacheBuilder
	        .newBuilder()
	        .expireAfterWrite(60, TimeUnit.MINUTES)
	        .build();
	private Map<String, String> weatherMap = new HashMap<String, String>();
	private WeatherService(){
		weatherMap.put("00", "晴");
		weatherMap.put("01", "多云");
		weatherMap.put("02", "阴");
		weatherMap.put("03", "阵雨");
		weatherMap.put("04", "雷阵雨");
		weatherMap.put("05", "雷阵雨伴有冰雹");
		weatherMap.put("06", "雨夹雪");
		weatherMap.put("07", "小雨");
		weatherMap.put("08", "中雨");
		weatherMap.put("09", "大雨");
		weatherMap.put("10", "暴雨");
		weatherMap.put("11", "大暴雨");
		weatherMap.put("12", "特大暴雨");
		weatherMap.put("13", "阵雪");
		weatherMap.put("14", "小雪");
		weatherMap.put("15", "中雪");
		weatherMap.put("16", "大雪");
		weatherMap.put("17", "暴雪");
		weatherMap.put("18", "雾");
		weatherMap.put("19", "冻雨");
		weatherMap.put("20", "沙尘暴");
		weatherMap.put("21", "小到中雨");
		weatherMap.put("22", "中到大雨");
		weatherMap.put("23", "大到暴雨");
		weatherMap.put("24", "暴雨到大暴雨");
		weatherMap.put("25", "大暴雨到特大暴雨");
		weatherMap.put("26", "小到中雪");
		weatherMap.put("27", "中到大雪");
		weatherMap.put("28", "大到暴雪");
		weatherMap.put("29", "浮尘");
		weatherMap.put("30", "扬沙");
		weatherMap.put("31", "扬沙");
		weatherMap.put("53", "霾");
		weatherMap.put("99", "无");
		JSON_FACTORY = new JacksonFactory();
		requestFactory = new NetHttpTransport().createRequestFactory(new HttpRequestInitializer() {
					@Override
					public void initialize(HttpRequest request) {
						request.setParser(new JsonObjectParser(JSON_FACTORY));
					}
				});
	};
	
	public JSONObject queryWeather(String cityOrArea ){
		JSONObject resultObject = new JSONObject();
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			WeatherMapper mapper = session.getMapper( WeatherMapper.class );
			String code =  mapper.getAreaCode(cityOrArea);
			if( code == null )
			{
				resultObject.put("ok", false);
				resultObject.put("message", "没要查询到["+cityOrArea+"]对应的数据");
			}else{
				JSONObject w = getWeatherData_v2(cityOrArea);
				if( w != null ){
					resultObject.put("weather", w);
				}
				JSONObject pm25 = getPM25Data(cityOrArea,code);
				if( pm25 != null )
					resultObject.put("pm25", pm25);
				if( pm25 != null || w != null)
					resultObject.put("ok", true);
				else{
					resultObject.put("ok", false);
					resultObject.put("messsage", "查询["+cityOrArea+"]数据失败" );
				}
			}
			return resultObject;
		}catch(Exception e){
			e.printStackTrace();
			resultObject.put("ok", false);
			resultObject.put("message", e.getMessage());
		}finally{
			if( session != null )
				session.close();
		}
		return resultObject;
	}
/*	
	private JSONObject getWeatherData(String code){
		try{
			JSONObject weatherData = weatherCache.getIfPresent( code );
			if( weatherData != null ){
				return weatherData;
			}else{
				weatherData = loadWeatherData(code);
				if( weatherData!=null )
					weatherCache.put(code, weatherData);
				return weatherData;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
*/	
	private JSONObject getWeatherData_v2(String city){
		try{
			JSONObject weatherData = weatherCache.getIfPresent( city );
			if( weatherData != null ){
				return weatherData;
			}else{
				weatherData = loadWeatherData_v2(city);
				if( weatherData!=null )
					weatherCache.put(city, weatherData);
				return weatherData;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
/*	
	private JSONObject loadWeatherData(String code){
		try{
			GenericUrl  url = new GenericUrl( String.format("http://www.weather.com.cn/data/sk/%s.html", code) );
			HttpRequest request = requestFactory.buildGetRequest(url);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				try{
					JSONObject obj = JSONObject.parseObject(resp.parseAsString());
					JSONObject info = obj.getJSONObject("weatherinfo");
					String weather = getForecastData(code);
					info.put("weather", weather);
					return info;
				}catch(Exception e){
					return null;
				}
			}else{
				logger.error("getWeatherData faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getWeatherData exception:",e);
		}
		return null;
	}
*/	
	private JSONObject loadWeatherData_v2(String city){
		try{
			GenericUrl  url = new GenericUrl( String.format("https://api.thinkpage.cn/v2/weather/now.json?city=%s&language=zh-chs&unit=c&key=0QBKLBBEC6", city) );
			HttpRequest request = requestFactory.buildGetRequest(url);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				try{
					JSONObject obj = JSONObject.parseObject(resp.parseAsString());
					String status = obj.getString("status");
					if( "OK".compareToIgnoreCase(status) == 0 ){
						JSONObject info = obj.getJSONArray("weather").getJSONObject(0);
						return info;
					}
					return null;
				}catch(Exception e){
					return null;
				}
			}else{
				logger.error("getWeatherData faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getWeatherData exception:",e);
		}
		return null;
	}
	
	private JSONObject getPM25Data(String city,String code){
		try{
			String cityName = city;
			if( !code.endsWith("0100") && !code.endsWith("0101")) {
				SqlSession session = null;
				try{
					session = DBUtils.getSqlSession();
					WeatherMapper mapper = session.getMapper( WeatherMapper.class );
					cityName =  mapper.getAreaName(code);
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					if( session != null )
						session.close();
				}
			}
			String reqUrl = String.format("http://www.pm25.in/api/querys/pm2_5.json?city=%s&token=YcgLt2BqCoQxHhW62qAz", cityName);
			GenericUrl  url = new GenericUrl( reqUrl );
			HttpRequest request = requestFactory.buildGetRequest(url);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				try{
					JSONArray array = JSON.parseArray(resp.parseAsString());
					return array.getJSONObject( array.size() - 1 );
				}catch(Exception e){
					return null;
				}
			}else{
				logger.error("getPM25Data faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getPM25Data exception:",e);
		}
		return null;
	}
	
	
/*	
	private String getForecastData(String code){
		try{
			String reqUrl = SmartWeatherUrlUtil.getInterfaceURL(code, "forecast_v");
			GenericUrl  url = new GenericUrl( reqUrl );
			HttpRequest request = requestFactory.buildGetRequest(url);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				try{
					JSONObject obj = JSONObject.parseObject(resp.parseAsString());
					JSONArray jsonarray = obj.getJSONObject("f").getJSONArray("f1");
					String fa = jsonarray.getJSONObject(0).getString("fa");
					String fb = jsonarray.getJSONObject(0).getString("fb");
					String weather = null;
					if(!fa.equals("")) {
						weather = weatherMap.get(fa);
					} else {
						weather = weatherMap.get(fb);				
					}
					return weather;
				}catch(Exception e){
					return null;
				}
			}else{
				logger.error("getForecastData faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getForecastData exception:",e);
		}
		return null;
	}
*/	
}
